#include "workCmd.h"
#include "md5.h"

int recvn(int sockfd, void *buf, int length){
    int total = 0;
    char *p = (char *)buf;
    while(total < length){
        ssize_t sret = recv(sockfd,p+total,length-total,0);
        total += sret;
    }
    return total;
}

int upload(int netFd,char *file){
    char filePath[1024] = {0};
    sprintf(filePath,"%s%s%s","upload","/",file);

    int fd = open(file,O_RDWR);
    ERROR_CHECK(fd,-1,"open");
    
    //发送文件名字
    train_t train;
    if(fd == -1){
        perror("open");
        bzero(&train,sizeof(train));
        send(netFd,&train,sizeof(train.length) + train.length,MSG_NOSIGNAL);
    }
    train.length = strlen(file);
    strcpy(train.data,file);
    int ret = send(netFd,&train,sizeof(train.length) + train.length,MSG_NOSIGNAL);
    ERROR_CHECK(ret ,-1,"sned");

    //发送文件总大小
    struct stat statbuf;
    fstat(fd,&statbuf);
    int filesize = statbuf.st_size;
    train.length = 4;
    memcpy(train.data,&filesize,sizeof(int));
    send(netFd,&train,sizeof(train.length) + train.length,MSG_NOSIGNAL);

    //发送md5
    char md5Str[MD5_STR_LEN + 1] = {0};
    Compute_file_md5(filePath,md5Str);
    train.length = strlen(md5Str);
    send(netFd,&train,sizeof(train.length) + train.length,MSG_NOSIGNAL);

    //确认是否上传
    int check = 0;
    recvn(netFd,&check,sizeof(check));
    if(check == 0){
        //不需要上传
        return 0;
    }

    //获得文件已传大小
    int clientSize = 0;
    bzero(&train,sizeof(train));
    recvn(netFd,&clientSize,sizeof(clientSize));
    printf("ClientFileSize = %d\n",clientSize);

    //分情况发送
    char *p = (char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    int total = clientSize;
    if(filesize >= 1073741824){
        //大文件
        printf("Hurge file.\n");
        send(netFd,p + total,filesize,MSG_NOSIGNAL);
    }else{
        //小文件
        printf("Tiny file.\n");
        while(total < filesize){
            if((filesize - total) < sizeof(train.data)){
                train.length = filesize - total;
            }else{
                train.length = sizeof(train.data);
            }
            memcpy(train.data,p + total,train.length);
            total = total + train.length;
            send(netFd,&train,sizeof(train.length) + train.length,MSG_NOSIGNAL);
        }
        train.length = 0;
        send(netFd,&train,sizeof(train.length) + train.length,MSG_NOSIGNAL);
    }
    close(fd);
    munmap(p,filesize);

    //获取发送用时
    int totalTime = 0;
    recvn(netFd,&totalTime,sizeof(totalTime));

    return 0;
}

int Dowload(int sockFd){
    //获取文件名字
    char name[1024] = {0};
    int dataLength = 0;
    recvn(sockFd,&dataLength,sizeof(dataLength));
    recvn(sockFd,name,dataLength);
    if(dataLength == 0){
        printf("Wrong file name.\n");
        return EXIT_FAILURE;
    }
    printf("name = %s\n",name);

    //获取文件大小，没有就创建
    char filePath[1024] = {0};
    sprintf(filePath,"%s%s%s","download","/",name);
    int fd = open(filePath,O_RDWR | O_CREAT,0666);
    ERROR_CHECK(fd,-1,"open");
    char buf[1024] = {0};
    int filesize = 0;
    recvn(sockFd,&dataLength,sizeof(dataLength));
    recvn(sockFd,&filesize,dataLength);

    //获取md5
    //获取是否上传
    

    //断点续传
    //检查是否有同名文件,并发送大小
    struct stat statbuf;
    int ret = fstat(fd,&statbuf);
    ERROR_CHECK(ret,-1,"fstat");
    int exitSzie = statbuf.st_size;
    send(sockFd,&exitSzie,sizeof(exitSzie),MSG_NOSIGNAL);
    lseek(fd,0,SEEK_END);

    //统计时间并上传
    time_t timeBeg, timeEnd;
    timeBeg = time(NULL);
    
    //分情况发送
    char *p = (char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    ERROR_CHECK(p,MAP_FAILED,"mmap");
    if(filesize >= 1073741824){
        //大文件
        printf("Hurge file.\n");
        ftruncate(fd,filesize);
        recvn(sockFd,p,filesize);
        timeEnd = time(NULL);
    }else{
        //小文件
        printf("Tiny file.\n");
        int currsize = 0;
        while(1){
            bzero(buf,sizeof(buf));
            ret = recv(sockFd,&dataLength,sizeof(dataLength),0);
            recvn(sockFd,buf,dataLength);
            if(dataLength == 0){
                timeEnd = time(NULL);
                break;
            }
            if(ret == 0){
                munmap(p,filesize);
                close(fd);
                return EXIT_FAILURE;
            }
            currsize += dataLength;
            printf("%5.2lf%%\r",100.0*currsize/filesize);
            fflush(stdout);

            write(fd,buf,dataLength);
        }
    }
    printf("100.00%%\n");
    close(fd);
    munmap(p,filesize);

    int totalTime = timeEnd - timeBeg;
    send(sockFd,&totalTime,sizeof(totalTime),MSG_NOSIGNAL);

    return 0;
}

